import http.cookiejar as cookielib
import urllib.request as ul
import urllib.parse as up
import json

# 先把cookie对象存储为cookiejar的对象
from tkinter import Image

c = cookielib.LWPCookieJar()
# 把cookiejar对象转换为一个handle
cookie = ul.HTTPCookieProcessor(c)
# 建立一个模拟浏览器，需要handle作为参数
opener = ul.build_opener(cookie)
# 安装一个全局模拟浏览器，代表无论怎么访问都是一个浏览器操作而不是分开获取验证码等msg
ul.install_opener(opener)

username = ''
password = ''
# 验证码获取url
code_url = "https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand&0.029809860982"
check_url = "https://kyfw.12306.cn/passport/captcha/captcha-check"
login_url = "https://kyfw.12306.cn/passport/web/login"
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0'}


def get_code():
    """
    获取验证码
    :return:
    """
    req = ul.Request(code_url)
    req.headers = headers
    code_file = opener.open(req).read()
    with open('.\code.png', 'wb') as f:
        f.write(code_file)


def check_code():
    input_indexs = get_code_index()
    code = get_code_by_index(input_indexs)
    req = ul.Request(check_url)
    req.headers = headers
    data = {
        'answer': code,
        'login_site': 'E',
        'rand': 'sjrand'
    }
    data = up.urlencode(data).encode()
    check_code_html = opener.open(req, data=data).read().decode()
    result = json.loads(check_code_html)
    if result['result_code'] == '4':
        print('验证码通过')
        login()
    else:
        print('验证码校验失败')


def get_code_index():
    # img = Image.open('.\code.png')
    # img.show()
    # img.close()  # 关闭后，不关闭显示图片
    # =======================================================================
    # 根据打开的图片识别验证码输入图片索引序号，有可以是1张、2张、3张图片的序号，序号之间用逗号隔开
    # 例如2，4，6,表示第1排第2，第2排第4,6张
    # ---------------------------------------
    #         |         |         |
    #    0    |    1    |    2    |     3
    #         |         |         |
    # ---------------------------------------
    #         |         |         |
    #    4    |    5    |    6    |     7
    #         |         |         |
    # ---------------------------------------
    # =======================================================================
    input_indexs = input('请输入验证码位置，以","分割（例如2,4,6）:')
    return input_indexs


def get_code_by_index(input_indexs):
    indexs = input_indexs.split(',')
    # 由于12306官方验证码是验证正确验证码的坐标范围,我们取每个验证码中点的坐标(大约值)
    img_center_position = ['35,35', '105,35', '175,35', '245,35', '35,105', '105,105', '175,105', '245,105']
    check_ok_list = []  # 例如得到：['175,35', '35,105', '175,105']
    for index in indexs:
        check_ok_list.append(img_center_position[int(index)])
        # 正确验证码的坐标拼接成字符串，作为网络请求时的参数
    check_ok_img_str = ','.join(check_ok_list)  # 生成的数据例如：175,35,35,105,175,105
    return check_ok_img_str


def login():
    """
    登录
    :return:
    """
    req = ul.Request(login_url)
    req.headers = headers
    data = {
        'username': username,
        'password': password,
        'appid': 'otn'
    }
    data = up.urlencode(data).encode()
    login_html = opener.open(req, data=data).read().decode()
    result = json.loads(login_html)
    if result['result_code'] == 0:
        print('账户密码验证通过')
    else:
        print(result['result_message'])


def input_account():
    global username
    global password
    username = '549226148@qq.com'
    password = 'yq1991812'


def run():
    input_account()
    get_code()
    check_code()


run()
